/*
 * processmgtbase.h
 *
 *  Created on: 2011-4-9
 *      Author: chenl
 */

#ifndef PROCESSMGTBASE_H_
#define PROCESSMGTBASE_H_

#include "common/common_def.h"
#include "common/common_type.h"
#include "common/common_util.h"
#include "logengine/simplelog.h"
#include "ps_error.h"
#include "global.h"
#include <ext/hash_map>
#include <deque>

#include "loki/Singleton.h"

#define for_each_task(MGT, QUEUE, P) \
	for (P = MGT.FirstTaskFrom##QUEUE(); NULL != P; P = MGT.NextTaskFrom##QUEUE(*P))

class CTask;

class CProcessMgtBase
{
protected:
	typedef std::deque<CTask*, DEFAULT_ALLOC<CTask*> > TaskQueue;
	typedef TaskQueue::iterator TaskQueueItr;
	typedef TaskQueue::const_iterator ConstTaskQueueItr;
	typedef __gnu_cxx ::hash_map<pid_t, CTask*, __gnu_cxx::hash<pid_t>,
			__gnu_cxx::equal_to<pid_t>, DEFAULT_ALLOC<CTask*> > TaskHashList;
	typedef TaskHashList::iterator TaskHashListItr;
	typedef TaskHashList::const_iterator ConstTaskHashLisItr;

public:
	CProcessMgtBase();
	virtual ~CProcessMgtBase();

public:
	int32_t Initialize();
	int32_t Uninitialize();
	int32_t Destroy();

public:
	CTask* CurrentTask()
	{
		return current_;
	}
	CTask* InitTask()
	{
		return init_;
	}
	CTask* GetTaskByPid(pid_t pid)
	{
		return GetTaskFromHashList(pid);
	}

	void SetCurrentTask(CTask& task)
	{
		current_ = &task;
	}

	int32_t NewTask(CTask& oldTask, CTask& newTask);

	int32_t DeleteTask(CTask& task);
	int32_t DeleteTask(pid_t pid);

	int32_t InsertToRunQueue(CTask& task);
	int32_t InsertToWaitQueue(CTask& task);
	int32_t InsertTaskToHashList(CTask& task);

	int32_t DelTaskFromRunqueue(CTask& task)
	{
		return DelTaskFromQueue(task, *pRunQueue_);
	}

	int32_t DelTaskFromWaitQueue(CTask& task)
	{
		return DelTaskFromQueue(task, *pWaitQueue_);
	}

	int32_t DelTaskFromHashList(pid_t pid)
	{
		// FIXME: how can we know if erase() succeed
		taskHashList_.erase(pid);
		return S_OK;
	}

	int32_t DelTaskFromProcessTree(CTask& task);

	CTask* GetTaskFromHashList(pid_t pid);

	CTask* PopFromRunQueue()
	{
		return PopFromQueue(*pRunQueue_);
	}
	CTask* PopFromWaitQueue()
	{
		return PopFromQueue(*pWaitQueue_);
	}

	CTask* FirstTaskFromRunQueue()
	{
		return FirstTask(*pRunQueue_);
	}
	CTask* NextTaskFromRunQueue(CTask& task)
	{
		return NextTask(task, *pRunQueue_);
	}

	CTask* FirstTaskFromWaitQueue()
	{
		return FirstTask(*pWaitQueue_);
	}
	CTask* NextTaskFromWaitQueue(CTask& task)
	{
		return NextTask(task, *pWaitQueue_);
	}

	int32_t MoveTaskToRunQueueTail(CTask&);
	int32_t MoveTaskToWaitQueueTail(CTask&);

	bool IsTaskOnRunQueue(const CTask& task);
	bool IsTaskOnWaitQueue(const CTask& task);
	bool IsTaskOnHashList(pid_t pid);

	bool IsRunQueueEmpty() const;
	bool IsWaitQueueEmpty() const;
	bool IsHashListEmpty() const;

protected:
	int32_t InsertTaskToQueue(CTask& task, TaskQueue& queue);

	TaskQueueItr FindTaskFromQueue(const CTask& task,
			const TaskQueue& queue);

	TaskHashListItr FindTaskFromHashList(pid_t pid)
	{
		TaskHashListItr itr = taskHashList_.find(pid);
		return itr;
	}

	int32_t DelTaskFromQueue(CTask& task, TaskQueue& queue);

	CTask* PopFromQueue(TaskQueue& queue)
	{
		CTask* pTask = FirstTask(queue);
		queue.pop_front();
		return pTask;
	}

	CTask* FirstTask(TaskQueue& queue)
	{
		if (queue.empty())
		{
			return NULL;
		}
		CTask* pTask = queue.front();
		return pTask;
	}
	CTask* NextTask(CTask& task, TaskQueue& queue);

public:
	CSimpleLog 			logEngine;

protected:
	CTask* 				init_;
	CTask* 				pRoot_; // process tree
	CTask* 				current_;
	TaskQueue* 			pRunQueue_;
	TaskQueue* 			pWaitQueue_;
	TaskQueue 			taskQueue_[2];
	TaskHashList 		taskHashList_;
};

typedef Loki::SingletonHolder<CProcessMgtBase> ProcessMgtBase;

#define CREATE_PROCESSMGTBASE_INSTANCE		ProcessMgtBase::Instance
#define GET_PROCESSMGTBASE_INSTANCE			ProcessMgtBase::Instance

#endif /* PROCESSMGTBASE_H_ */
